package com.example.spring.code.a02;

import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Collection;

public class TestBeanFactory {

    public static void main(String[] args) {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 添加 bean 定义，beanFactory 根据 bean 定义创建 bean
        // bean 的定义 （class、scope、初始化、销毁）
        AbstractBeanDefinition beanDefinition =
                BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("config", beanDefinition);

        System.out.println("==================添加后处理器之前==================");
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        // 给 beanFactory 添加一些常用的后处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        System.out.println("==================添加后处理器之后==================");
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        // 调用BeanFactory后处理，使其发挥作用
        // BeanFactoryPostProcessor 主要功能，补充了一些 bean 的定义
        Collection<BeanFactoryPostProcessor> beanFactoryPostProcessors =
                beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values();
        beanFactoryPostProcessors.stream().forEach(beanFactoryPostProcessor -> {
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });

        System.out.println("==================添加BeanFactory后处理器，并使其发挥作用==================");
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        // Bean 后处理器，针对 bean 的生命周期的各个阶段提供扩展，例如 @Autowired、@Resource ...
        System.out.println("==================Bean后处理器发挥作用之前==================");
//        System.out.println(beanFactory.getBean(Bean1.class).getBean2());
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanPostProcessor -> {
            beanFactory.addBeanPostProcessor(beanPostProcessor);
        });
        System.out.println("==================Bean后处理器发挥作用之后==================");
        System.out.println(beanFactory.getBean(Bean1.class).getBean2());

        /*
            学到了什么
                1. beanFactory 不会主动调用 BeanFactory 后处理器
                2. beanFactory 不会主动添加 Bean 后处理器
                3. beanFactory 不会主动初始化单例
                4. beanFactory 不会解析 ${} 与 #{}

                bean 后处理会有排序的逻辑
         */

    }

    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }
        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }
        @Bean
        public Bean3 bean3() {
            return new Bean3();
        }
        @Bean
        public Bean4 bean4() {
            return new Bean4();
        }
    }

    interface Inter {

    }

    static class Bean3 implements Inter {}

    static class Bean4 implements Inter {}

    static class Bean1 {
        private static final Logger log = LoggerFactory.getLogger(Bean1.class);

        public Bean1() {
            log.info("构造 Bean1()");
        }

        @Autowired
        private Bean2 bean2;

        public Bean2 getBean2() {
            return bean2;
        }

        @Autowired
        @Resource
        private Inter bean3;

        public Inter getInter() {
            return bean3;
        }

    }

    static class Bean2 {
        private static final Logger log = LoggerFactory.getLogger(Bean2.class);

        public Bean2() {
            log.info("构造 Bean2()");
        }
    }

}
